﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using SharpDiary.Core.Utility;

namespace SharpDiary.Core.Controls
{
    public partial class ListItemControlBase : UserControl
    {
        #region Fields & Properties

        private Font _selectedItemFont;
        protected Color _selectedItemBackColor = Color.FromArgb(74, 120, 222);
        private LinearGradientBrush _normalItemBkBrush;
        private LinearGradientBrush _mouseEnterItemBkBrush;
        private LinearGradientBrush _selectedItemBkBrush;
        private Pen _selectedItemBorderPenOuter = new Pen(Color.FromArgb(183, 231, 252));
        private Pen _selectedItemBorderPenInner = new Pen(Color.FromArgb(223, 242, 253), 1);
        private Pen _topLinePen = new Pen(Color.FromArgb(230, 230, 230), 1);
        private MouseStatus _mouseStatus = MouseStatus.Normal;
        private bool _isSelected = false;
        private bool _showPageConer = false;


        private Color _titleForeColor;
        private Color _contentForeColor;
        private Color _createdDatetimeForeColor;

        /// <summary>
        /// 获取或设置是否显示右侧页角。
        /// </summary>
        public bool ShowPageConer
        {
            get { return _showPageConer; }
            set
            {
                _showPageConer = value;
            }
        }

        /// <summary>
        /// 被选中后触发此事件。
        /// </summary>
        public event EventHandler<EventArgs> Selected;

        protected virtual void OnSelected(object sender, EventArgs e)
        {
            if (Selected != null) { Selected(sender, e); }
        }

        private ContextMenu _popupMenu;

        /// <summary>
        /// 获取或设置右键快捷菜单。
        /// </summary>
        public ContextMenu PopupMenu
        {
            get { return _popupMenu; }
            set { _popupMenu = value; }
        }

        /// <summary>
        /// 获取或设置是否处于选中状态。
        /// </summary>
        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                if (value == _isSelected) { return; }

                _isSelected = value;

                _mouseStatus = (value ? MouseStatus.MouseClick : MouseStatus.Normal);
                UpdateSelectedState(value);

                //Invalidate(false);
                UpdateBackgroundImage();
            }
        }

        public Button ButtonEdit
        {
            get { return btnEdit; }
        }

        public Image Logo
        {
            get { return panelImage.BackgroundImage; }
            set
            {
                panelImage.BackgroundImage = value;
            }
        }

        public string Title
        {
            get { return lblName.Text; }
            set { lblName.Text = value; }
        }

        public string Description
        {
            get { return lblDescription.Text; }
            set { lblDescription.Text = value; }
        }

        public string CreatedAndUpdateDatetime
        {
            get { return lblCreateAndUpdateDatetime.Text; }
            set { lblCreateAndUpdateDatetime.Text = value; }
        }

        public Image ImageAboveLogo
        {
            get { return lblImageAboveLogo.Image; }
            set { lblImageAboveLogo.Image = value; }
        }

        #endregion

        #region Constructors

        public ListItemControlBase()
        {
            InitializeComponent();

            DoubleBuffered = true;
            ResizeRedraw = true;

            _topLinePen.DashStyle = DashStyle.Dot;
            _titleForeColor = lblName.ForeColor;
            _contentForeColor = lblDescription.ForeColor;
            _createdDatetimeForeColor = lblCreateAndUpdateDatetime.ForeColor;

            this.MouseDoubleClick += new MouseEventHandler(this.Control_MouseDoubleClick);

            UpdateBrushes();
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            DisplayItemInfo();
        }

        #endregion

        /// <summary>
        /// 更新选择状态。
        /// </summary>
        /// <param name="selected"></param>
        protected virtual void UpdateSelectedState(bool selected)
        {
            UpdateAllContainedControlState(this, selected);

            if (_showPageConer)
            {
                if (selected)
                {
                    imageButtonClose.BackColor = Color.FromArgb(210, 210, 210);
                }
                else
                {
                    imageButtonClose.BackColor = Color.Transparent;
                }
            }
        }

        /// <summary>
        /// 更新所有子控件的状态。
        /// </summary>
        /// <param name="parentControl"></param>
        /// <param name="selected"></param>
        private void UpdateAllContainedControlState(Control parentControl, bool selected)
        {
            if (!(parentControl is TextBox) && !(parentControl is RichTextBox))
            {
                parentControl.ForeColor = (!(parentControl is Button) && (parentControl != this) && selected ?
                        Color.FromArgb(parentControl.ForeColor.ToArgb() ^ 0xffffff) :
                        Color.FromKnownColor(KnownColor.ControlText));
            }

            //Tag = 1 的组件自动根据当前项的选中状态设置可见性。
            if (parentControl.Tag != null && parentControl.Tag.ToString() == "1")
            {
                if (parentControl == lblPaperConer)
                {
                    parentControl.Visible = _showPageConer && selected;
                }
                else
                {
                    parentControl.Visible = selected;
                }
            }

            foreach (Control control in parentControl.Controls)
            {
                UpdateAllContainedControlState(control, selected);
            }
        }

        protected override void OnControlAdded(ControlEventArgs e)
        {
            base.OnControlAdded(e);

            BindControlsEvents(e.Control);
            /*
            e.Control.ControlAdded -= Control_ControlAdded;
            e.Control.MouseEnter -= Control_MouseEnter;
            e.Control.MouseLeave -= Control_MouseLeave;
            e.Control.MouseDown -= Control_MouseDown;
            e.Control.MouseDoubleClick -= Control_MouseDoubleClick;

            e.Control.ControlAdded += new ControlEventHandler(Control_ControlAdded);
            e.Control.MouseEnter += new EventHandler(Control_MouseEnter);
            e.Control.MouseLeave += new EventHandler(Control_MouseLeave);
            e.Control.MouseDown += new MouseEventHandler(Control_MouseDown);
            e.Control.MouseDoubleClick += new MouseEventHandler(Control_MouseDoubleClick);
            */
        }

        void Control_ControlAdded(object sender, ControlEventArgs e)
        {
            e.Control.MouseEnter -= Control_MouseEnter;
            e.Control.MouseLeave -= Control_MouseLeave;
            e.Control.MouseDown -= Control_MouseDown;
            e.Control.MouseDoubleClick -= Control_MouseDoubleClick;

            e.Control.MouseEnter += new EventHandler(Control_MouseEnter);
            e.Control.MouseLeave += new EventHandler(Control_MouseLeave);
            //e.Control.Click += new EventHandler(Control_Click);
            e.Control.MouseDown += new MouseEventHandler(Control_MouseDown);
            e.Control.MouseDoubleClick += new MouseEventHandler(Control_MouseDoubleClick);
        }

        /// <summary>
        ///  为指定的 Control 及其所有子孙 Control 绑定相关事件。
        /// </summary>
        /// <param name="parentControl"></param>
        protected virtual void BindControlsEvents(Control parentControl)
        {
            parentControl.MouseEnter -= Control_MouseEnter;
            parentControl.MouseLeave -= Control_MouseLeave;
            parentControl.MouseDown -= Control_MouseDown;
            parentControl.MouseDoubleClick -= Control_MouseDoubleClick;

            parentControl.MouseEnter += new EventHandler(Control_MouseEnter);
            parentControl.MouseLeave += new EventHandler(Control_MouseLeave);
            //e.Control.Click += new EventHandler(Control_Click);
            parentControl.MouseDown += new MouseEventHandler(Control_MouseDown);
            parentControl.MouseDoubleClick += new MouseEventHandler(Control_MouseDoubleClick);

            foreach (Control subControl in parentControl.Controls)
            {
                BindControlsEvents(subControl);
            }
        }

        /// <summary>
        /// 编辑按钮被按下时触发此事件。
        /// </summary>
        public event EventHandler<EventArgs> EditButtonClick;

        protected virtual void OnEditButtonClick(object sender, EventArgs e)
        {
            if (EditButtonClick != null) { EditButtonClick(sender, e); }
        }

        /// <summary>
        /// 删除按钮被按下时触发此事件。
        /// </summary>
        public event EventHandler<EventArgs> DeleteButtonClick;

        protected virtual void OnDeleteButtonClick(object sender, EventArgs e)
        {
            if (DeleteButtonClick != null) { DeleteButtonClick(sender, e); }
        }

        /// <summary>
        /// 被删除后触发此事件。
        /// </summary>
        public event EventHandler<RemovedEventArgs> Removed;

        protected virtual void OnRemoved(object sender, RemovedEventArgs e)
        {
            if (Removed != null) { Removed(sender, e); }
        }

        /// <summary>
        /// 显示项信息。
        /// </summary>
        protected virtual void DisplayItemInfo()
        {

        }

        private void Control_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right) { return; }
            OnEditButtonClick(btnEdit, EventArgs.Empty);
        }

        private void Control_MouseDown(object sender, MouseEventArgs e)
        {
            if (_mouseStatus != MouseStatus.MouseClick)
            {
                _isSelected = true;
                _mouseStatus = MouseStatus.MouseClick;

                UpdateSelectedState(_isSelected);

                //Invalidate(false);
                UpdateBackgroundImage();

                OnSelected(this, EventArgs.Empty);
            }

            if (e.Button == MouseButtons.Right && _popupMenu != null)
            {
                _popupMenu.Show(this, PointToClient(Cursor.Position));
            }
        }

        private void Control_Click(object sender, EventArgs e)
        {
            if (_mouseStatus != MouseStatus.MouseClick)
            {
                _isSelected = true;
                _mouseStatus = MouseStatus.MouseClick;

                UpdateSelectedState(_isSelected);

                //Invalidate(false);
                UpdateBackgroundImage();

                OnSelected(this, EventArgs.Empty);
            }

            if (sender == btnEdit)
            {
                OnEditButtonClick(btnEdit, EventArgs.Empty);
            }
        }

        private void Control_MouseLeave(object sender, EventArgs e)
        {
            // if (_mouseStatus != MouseStatus.Normal && !_isSelected && !this.ClientRectangle.Contains(PointToClient(Cursor.Position)))
            if (_mouseStatus != MouseStatus.Normal && !_isSelected)
            {
                _mouseStatus = MouseStatus.Normal;
                //Invalidate(false);
                UpdateBackgroundImage();

                //Console.WriteLine("Control_MouseLeave");
            }
        }

        private void Control_MouseEnter(object sender, EventArgs e)
        {
            if (_mouseStatus != MouseStatus.MouseEnter && _mouseStatus == MouseStatus.Normal)
            {
                _mouseStatus = MouseStatus.MouseEnter;

                //Invalidate(false);
                UpdateBackgroundImage();

                //Console.WriteLine("Control_MouseEnter");
            }
        }

        /// <summary>
        /// 更新画笔。
        /// </summary>
        private void UpdateBrushes()
        {
            if (this.ClientRectangle.Width == 0 || this.ClientRectangle.Height == 0) { return; }

            _normalItemBkBrush = new LinearGradientBrush(this.ClientRectangle, Color.FromArgb(252, 251, 252), Color.FromArgb(244, 244, 244), 90);
            _mouseEnterItemBkBrush = new LinearGradientBrush(this.ClientRectangle, Color.FromArgb(233, 247, 254), Color.FromArgb(197, 233, 251), 90);
            _selectedItemBkBrush = new LinearGradientBrush(this.ClientRectangle, Color.FromArgb(53, 154, 255), Color.FromArgb(89, 172, 255), 90);
        }

        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);

            UpdateBrushes();
        }

        private void UpdateBackgroundImage()
        {
            if (!_isSelected)
            {
                switch (_mouseStatus)
                {
                    case MouseStatus.Normal:
                        {
                            //e.Graphics.FillRectangle(_normalItemBkBrush, this.ClientRectangle);
                            //Graphics.FromHwnd(this.Handle).DrawLine(_topLinePen, new Point(0, 0), new Point(this.Width, 0));
                            this.BackgroundImage = null;
                            this.BackColor = Color.WhiteSmoke;

                            break;
                        }
                    case MouseStatus.MouseEnter:
                        {
                            this.BackgroundImage = global::SharpDiary.Core.Properties.Resources.ListItemBk;

                            break;
                        }
                    case MouseStatus.MouseClick:
                        {
                            //this.BackgroundImage = global::SharpDiary.Core.Properties.Resources.SelectedListItemBk;
                            this.BackColor = _selectedItemBackColor;

                            break;
                        }
                }
            }
            else
            {
                //this.BackgroundImage = global::SharpDiary.Core.Properties.Resources.SelectedListItemBk;
                this.BackgroundImage = null;
                this.BackColor = Color.FromArgb(74, 120, 222);
            }
        }

        /*
        protected override void OnPaintBackground(PaintEventArgs e)
        {
            if (!_isSelected)
            {
                switch (_mouseStatus)
                {
                    case MouseStatus.Normal:
                        {
                            e.Graphics.FillRectangle(_normalItemBkBrush, this.ClientRectangle);
                            e.Graphics.DrawLine(_topLinePen, new Point(0, 0), new Point(this.Width, 0));

                            break;
                        }
                    case MouseStatus.MouseEnter:
                        {
                            e.Graphics.FillRectangle(_mouseEnterItemBkBrush, this.ClientRectangle);

                            break;
                        }
                    case MouseStatus.MouseClick:
                        {
                            e.Graphics.FillRectangle(_selectedItemBkBrush, this.ClientRectangle);

                            break;
                        }
                }
            }
            else
            {
                e.Graphics.FillRectangle(_selectedItemBkBrush, this.ClientRectangle);
                ControlPaint.DrawFocusRectangle(e.Graphics, this.ClientRectangle);
            }
        }
        */

        protected override void OnPaintBackground(PaintEventArgs e)
        {
            base.OnPaintBackground(e);

            if (!this.IsSelected)
            {
                e.Graphics.DrawLine(_topLinePen, new Point(0, 0), new Point(this.Width, 0));
            }
        }

        private void imageButtonClose_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                OnDeleteButtonClick(imageButtonClose, EventArgs.Empty);
            }
        }
    }

    public class RemovedEventArgs : EventArgs
    {
        public RemovedEventArgs() { }
    }
}
